package com.bjpowernode.config;

import com.bjpowernode.config.filter.JwtVerifyFilter;
import com.bjpowernode.config.handler.AppAuthenticationFailureHandler;
import com.bjpowernode.config.handler.AppAuthenticationSuccessHandler;
import com.bjpowernode.config.handler.AppLogoutSuccessHandler;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.logout.LogoutFilter;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.CorsConfigurationSource;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;

import java.util.Arrays;
import java.util.concurrent.ThreadPoolExecutor;

/**
 * 配置类
 */
@Configuration
@Slf4j
public class Config {

    @Resource
    private AppAuthenticationSuccessHandler appAuthenticationSuccessHandler;

    @Resource
    private AppAuthenticationFailureHandler appAuthenticationFailureHandler;

    @Resource
    private JwtVerifyFilter jwtVerifyFilter;

    @Resource
    private AppLogoutSuccessHandler appLogoutSuccessHandler;


    @Bean
    public PasswordEncoder passwordEncoder(){
        return new BCryptPasswordEncoder();
    }


    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity httpSecurity , CorsConfigurationSource configurationSource) throws Exception {
        return httpSecurity.formLogin(formLogin -> {
                    formLogin.loginProcessingUrl("/api/login")
                            .usernameParameter("loginAct")
                            .passwordParameter("loginPwd")
                            .successHandler(appAuthenticationSuccessHandler)
                            .failureHandler(appAuthenticationFailureHandler);
                })
                // 跨站请求伪造 -- 网络安全问题
                .csrf(AbstractHttpConfigurer::disable)
                // 跨域问题
                .cors(cors -> {
                    cors.configurationSource(configurationSource);
                })
                // 禁用session , 前后端分离是无状态的 , 修改会话创建策略
                .sessionManagement(sessionManagement -> {
                    sessionManagement.sessionCreationPolicy(SessionCreationPolicy.NEVER);
                })
                // 在登录之前 , 添加jwt过滤器
                // 兼容退出功能
                .addFilterBefore(jwtVerifyFilter, LogoutFilter.class)
                // .addFilterAfter(jwtVerifyFilter, UsernamePasswordAuthenticationFilter.class)
                // 退出
                .logout(logout -> {
                    logout.logoutUrl("/api/logout")  // 指定退出登录提交到那个地址上
                            .logoutSuccessHandler(appLogoutSuccessHandler);
                })
                .build();
    }

    /**
     * 解决跨域问题
     * @return
     */
    @Bean
    public CorsConfigurationSource configurationSource(){
        CorsConfiguration corsConfiguration = new CorsConfiguration();
        corsConfiguration.setAllowedOrigins(Arrays.asList("*"));
        corsConfiguration.setAllowedMethods(Arrays.asList("*"));
        corsConfiguration.setAllowedHeaders(Arrays.asList("*"));

        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", corsConfiguration);
        return source;
    }


    /**
     * 自定义异步执行任务线程池
     */
    @Bean
    public ThreadPoolTaskExecutor threadPoolTaskExecutor() {
        log.info("start asyncExecutor........");
        ThreadPoolTaskExecutor threadPoolTaskExecutor = new ThreadPoolTaskExecutor();
        //配置核心线程数
        threadPoolTaskExecutor.setCorePoolSize(16);
        //配置最大线程数
        threadPoolTaskExecutor.setMaxPoolSize(64);
        //配置队列大小
        threadPoolTaskExecutor.setQueueCapacity(9999);
        //配置线程池中的线程的名称前缀
        threadPoolTaskExecutor.setThreadNamePrefix("async-order-");
        // rejection-policy：当pool已经达到max pool size的时候，如何处理新任务
        // CALLER_RUNS：不在新线程中执行任务，而是由调用线程（提交任务的线程）处理该任务
        threadPoolTaskExecutor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        //  threadPoolTaskExecutor.setRejectedExecutionHandler(new ThreadPoolExecutor.DiscardOldestPolicy());
        // threadPoolTaskExecutor.setRejectedExecutionHandler(new ThreadPoolExecutor.AbortPolicy());
        // threadPoolTaskExecutor.setRejectedExecutionHandler(new ThreadPoolExecutor.DiscardPolicy());
        //执行初始化
        threadPoolTaskExecutor.initialize();
        return threadPoolTaskExecutor;
    }
}
